
import java.awt.*;
import javax.swing.*;

// a class representing an AVL basic type paired with a GUI representation
public class AVLBasicType extends JPanel {
	String identifier;
	Object value;
	Object old;
	Color background;
	boolean showold;
	boolean getandset;
	Color BACKGROUND = Color.WHITE;
	Color FOREGROUND = Color.BLACK;
	Color GETHIGHLIGHT = Color.CYAN;
	Color SETHIGHLIGHT = Color.MAGENTA;
	final int WIDTH = 50;
	final int HEIGHT = 50;
	private static final long serialVersionUID = 1L;

	// constructs an AVLBasicType
	public AVLBasicType(String identifier, Object value) {
		super();
		this.identifier = identifier;
		this.setPreferredSize(new Dimension(this.WIDTH, this.HEIGHT));
		this.setMinimumSize(new Dimension(this.WIDTH, this.HEIGHT));
		this.setSize(new Dimension(this.WIDTH, this.HEIGHT));
		this.value = value;
		this.background = this.BACKGROUND;
		this.showold = false;
		this.getandset = false;
	}

	// returns the value of this AVLBasicType and highlights its GUI representation, if any
	public Object get() {
		if(background.equals(this.SETHIGHLIGHT))
			getandset = true;
		background = this.GETHIGHLIGHT;
		this.repaint();
		return value;
	}

	// returns the value of this AVLBasicType without highlighting its GUI representation, if any
	public Object getSilently() {
		return value;
	}

	// sets the background color of this AVLBasicType's GUI representation
	public void setAVLBackground(Color background) {
		if(BACKGROUND.equals(this.background))
			this.background = background;
		BACKGROUND = background;
		this.repaint();
	}

	// sets the value of this AVLBasicType and highlights its GUI representation, if any
	public void set(Object value) {
		if(background.equals(this.GETHIGHLIGHT))
			getandset = true;
		this.old = this.value;
		this.value = value;
		background = this.SETHIGHLIGHT;
		this.showold = true;
		this.repaint();
	}

	// resets the GUI representation of this AVLBasicType, if any
	public void reset() {
		this.getandset = false;
		this.showold = false;
		this.background = this.BACKGROUND;
		this.repaint();
	}

	// draws an AVLBasicType GUI representation
	public void paint(Graphics g) {

		// draw background
		Rectangle r = new Rectangle(0, 0, this.WIDTH, this.HEIGHT);
		g.setColor(background);
		g.fillRect(r.x, r.y, r.width-1, r.height-1);
		if(getandset) {
			if(background == this.GETHIGHLIGHT)
				g.setColor(this.SETHIGHLIGHT);
			else
				g.setColor(this.GETHIGHLIGHT);
			int[] x = {r.x, r.x+r.width-1, r.x};
			int[] y = {r.y, r.y, r.y+r.height-1};
			g.fillPolygon(x, y, 3);
		}

		// draw border
		g.setColor(this.FOREGROUND);
		g.drawRect(r.x, r.y, r.width-1, r.height-1);

		// draw identifier
		FontMetrics fm = g.getFontMetrics();
		while(fm.stringWidth(identifier) >= this.WIDTH-5)
			identifier = identifier.substring(0, identifier.length()-1);
		g.drawString(identifier, r.x+r.width/2-fm.stringWidth(identifier)/2, r.y+15);

		// draw value
		g.drawString(value.toString(), r.x+r.width/2-fm.stringWidth(value.toString())/2, r.y+r.height/2+4);

		// draw old value if enabled
		if(showold) {
			g.drawString(old.toString(), r.x+r.width/2-fm.stringWidth(old.toString())/2, r.y+r.height-6);
			g.drawLine(r.x+r.width/2-fm.stringWidth(old.toString())/2-2, r.y+r.height-11, r.x+r.width/2+fm.stringWidth(old.toString())/2+2, r.y+r.height-11);
		}
	}
}
